# encoding: utf-8
# @File  : dashboard.py
# @Author: shaoyun
# @Date  :  2025/05/29

from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Path
from sqlalchemy.orm import Session
from starlette.status import HTTP_404_NOT_FOUND
from app.api.dependencies import get_current_user, get_db
from app.models.user import User
from app.models.task import Task, TaskStatus
from app.db.mongo_manager import MongoDB
from app.services.monitor import Monitor

router = APIRouter()


@router.get("/stats", response_model=Dict[str, Any])
async def get_dashboard_stats(
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """获取仪表盘统计数据"""
    # 获取任务统计
    tasks_query = db.query(Task)
    if current_user.role.value != "admin":
        tasks_query = tasks_query.filter(Task.user_id == current_user.id)

    all_tasks = tasks_query.all()
    task_count = len(all_tasks)
    running_task_count = len([t for t in all_tasks if t.status == TaskStatus.RUNNING])
    completed_task_count = len([t for t in all_tasks if t.status == TaskStatus.COMPLETED])

    # 获取爬虫统计
    spiders_query = {} if current_user.role.value == "admin" else {"user_id": current_user.id}
    spiders = await MongoDB.find_many("spiders", spiders_query)
    spider_count = len(spiders)
    python_spider_count = len([s for s in spiders if s["language"].lower() == "python"])
    js_spider_count = len([s for s in spiders if s["language"].lower() == "javascript"])

    # 获取节点统计
    nodes = await MongoDB.find_many("nodes", {})
    node_count = len(nodes)
    online_node_count = len([n for n in nodes if n.get("status") == "online"])
    offline_node_count = node_count - online_node_count

    # 获取今日任务统计
    today = datetime.utcnow().date()
    today_tasks = [
        t for t in all_tasks
        if t.created_at.date() == today
    ]
    today_task_count = len(today_tasks)
    today_success_count = len([t for t in today_tasks if t.status == TaskStatus.COMPLETED])
    today_fail_count = len([t for t in today_tasks if t.status == TaskStatus.FAILED])

    return {
        "taskCount": task_count,
        "runningTaskCount": running_task_count,
        "completedTaskCount": completed_task_count,
        "spiderCount": spider_count,
        "pythonSpiderCount": python_spider_count,
        "jsSpiderCount": js_spider_count,
        "nodeCount": node_count,
        "onlineNodeCount": online_node_count,
        "offlineNodeCount": offline_node_count,
        "todayTaskCount": today_task_count,
        "todaySuccessCount": today_success_count,
        "todayFailCount": today_fail_count
    }


@router.get("/task-trend", response_model=Dict[str, Any])
async def get_task_trend(
        days: int = Query(7, ge=1, le=30),
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """获取任务执行趋势数据"""
    end_date = datetime.utcnow().date()
    start_date = end_date - timedelta(days=days - 1)

    tasks_query = db.query(Task)
    if current_user.role.value != "admin":
        tasks_query = tasks_query.filter(Task.user_id == current_user.id)

    tasks = tasks_query.filter(Task.created_at >= start_date).all()

    dates = [(start_date + timedelta(days=i)).isoformat() for i in range(days)]
    completed = [0] * days
    failed = [0] * days

    for task in tasks:
        day_index = (task.created_at.date() - start_date).days
        if 0 <= day_index < days:
            if task.status == TaskStatus.COMPLETED:
                completed[day_index] += 1
            elif task.status == TaskStatus.FAILED:
                failed[day_index] += 1

    return {
        "dates": dates,
        "completed": completed,
        "failed": failed
    }


@router.get("/data-distribution", response_model=Dict[str, Any])
async def get_data_distribution(
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """获取数据采集分布"""
    tasks_query = db.query(Task)
    if current_user.role.value != "admin":
        tasks_query = tasks_query.filter(Task.user_id == current_user.id)

    tasks = tasks_query.all()
    spider_ids = list(set(t.spider_id for t in tasks if t.spider_id))

    categories = []
    values = []

    for spider_id in spider_ids:
        spider = await MongoDB.find_one("spiders", {"_id": spider_id})
        if spider:
            spider_name = spider["name"]
            task_count = len([t for t in tasks if t.spider_id == spider_id])
            categories.append(spider_name)
            values.append(task_count)

    return {
        "categories": categories,
        "values": values
    }


@router.get("/recent-tasks", response_model=List[Dict[str, Any]])
async def get_recent_tasks(
        limit: int = Query(10, ge=1, le=100),
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """获取最近任务"""
    tasks_query = db.query(Task)
    if current_user.role.value != "admin":
        tasks_query = tasks_query.filter(Task.user_id == current_user.id)

    tasks = tasks_query.order_by(Task.created_at.desc()).limit(limit).all()

    recent_tasks = []
    for task in tasks:
        spider = await MongoDB.find_one("spiders", {"_id": task.spider_id})
        task_data = {
            "id": task.id,
            "name": task.name,
            "spider_name": spider["name"] if spider else "未知",
            "status": task.status.value,
            "created_at": task.created_at.isoformat()
        }
        recent_tasks.append(task_data)

    return recent_tasks


@router.get("/system-status", response_model=Dict[str, Any])
async def get_system_status(
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """获取系统状态"""
    metrics = await Monitor.get_system_metrics(db, "hour")
    return {
        "cpuUsage": metrics.get("cpu_usage", 0),
        "memoryUsage": metrics.get("memory_usage", 0),
        "diskUsage": metrics.get("disk_usage", 0),
        "uptime": metrics.get("uptime", "未知"),
        "version": "v0.1.0"
    }


@router.post("/tasks/{task_id}/restart", response_model=Dict[str, Any])
async def restart_task(
        task_id: str = Path(...),
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """重启任务"""
    from app.services.task_scheduler import TaskScheduler

    task = await TaskScheduler.get_task(db=db, task_id=task_id)
    if not task:
        raise HTTPException(
            status_code=HTTP_404_NOT_FOUND,
            detail="Task not found"
        )

    # 检查权限
    if current_user.role.value != "admin" and task.user_id != current_user.id:
        raise HTTPException(
            status_code=403,
            detail="Not authorized to restart this task"
        )

    # 只有已完成或失败的任务可以重启
    if task.status not in [TaskStatus.COMPLETED, TaskStatus.FAILED]:
        raise HTTPException(
            status_code=400,
            detail=f"Cannot restart task with status: {task.status.value}"
        )

    # 创建新任务，复制原任务的参数
    new_task = await TaskScheduler.create_task(
        db=db,
        user_id=task.user_id,
        spider_id=task.spider_id,
        name=f"Restarted: {task.name}",
        parameters=task.parameters,
        priority=task.priority,
        cron=None  # 重启任务不设置定时
    )

    return {
        "success": True,
        "message": "Task restarted successfully",
        "new_task_id": new_task.id
    }


@router.get("/export/{type}", response_model=Dict[str, Any])
async def export_chart_data(
        type: str = Path(..., description="导出类型: trend 或 distribution"),
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """导出图表数据"""
    if type == "trend":
        data = await get_task_trend(days=7, db=db, current_user=current_user)
    elif type == "distribution":
        data = await get_data_distribution(db=db, current_user=current_user)
    else:
        raise HTTPException(status_code=400, detail="Invalid export type")

    # 简单模拟导出数据为 CSV 格式（实际应用中可使用 pandas 或其他库生成 Excel）
    if type == "trend":
        csv_content = "Date,Completed,Failed\n"
        for i in range(len(data["dates"])):
            csv_content += f"{data['dates'][i]},{data['completed'][i]},{data['failed'][i]}\n"
    else:
        csv_content = "Category,Value\n"
        for i in range(len(data["categories"])):
            csv_content += f"{data['categories'][i]},{data['values'][i]}\n"

    return {
        "content": csv_content,
        "filename": f"{type}_data_{datetime.utcnow().date().isoformat()}.csv"
    }